package io.jpress.codegen;

import com.jfinal.log.Log;
import io.jboot.utils.FileUtil;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.*;

public class FilesCopyer {
    private static final Log LOG = Log.getLog(FilesCopyer.class);

    private String from;
    private String target;

    private final Set<String> ignoreFiles = new HashSet<>();
    private final Set<String> ignoreSuffix = new HashSet<>();
    private final Set<String> ignorePrefix = new HashSet<>();

    private FileFilter ignoreFilter;

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTarget() {
        return target;
    }

    public void setTarget(String target) {
        this.target = target;
    }

    public Set<String> getIgnoreFiles() {
        return ignoreFiles;
    }

    public void addIgnoreFiles(String... strings) {
        for (String string : strings) {
            ignoreFiles.add(string);
        }
    }

    public void addIgnoreFiles(Collection<String> strings) {
        ignoreFiles.addAll(strings);
    }

    public void addIgnoreSuffix(String... strings) {
        for (String string : strings) {
            ignoreSuffix.add(string);
        }
    }

    public void addIgnoreSuffix(Collection<String> strings) {
        ignoreSuffix.addAll(strings);
    }


    public void addIgnorePrefix(String... strings) {
        for (String string : strings) {
            ignorePrefix.add(string);
        }
    }

    public void addIgnorePrefix(Collection<String> strings) {
        ignorePrefix.addAll(strings);
    }


    public FileFilter getIgnoreFilter() {
        return ignoreFilter;
    }

    public void setIgnoreFilter(FileFilter ignoreFilter) {
        this.ignoreFilter = ignoreFilter;
    }

    public void startCopy() {
        File fromFile = new File(from);
        if (!fromFile.exists()) {
            LOG.error("from file {} not exists", fromFile);
            return;
        }

        if (!fromFile.isDirectory()) {
            LOG.error("from file {} is not directory.", fromFile);
            return;
        }

        File targetFile = new File(target);
        if (targetFile.exists() && !targetFile.isDirectory()) {
            LOG.error("target file {} is not directory.", targetFile);
            return;
        }

        List<File> fromFiles = new ArrayList<>();
        fillFromFiles(fromFile, fromFiles);

        if (fromFiles.isEmpty()) {
            LOG.error("fromFiles is empty.");
            return;
        }

        int len = FileUtil.getCanonicalPath(fromFile).length();
        for (File file : fromFiles) {
            String relativePath = FileUtil.getCanonicalPath(file).substring(len);
            try {
                System.out.println("copy>>>>" + file);
                FileUtils.copyFile(file, new File(targetFile, relativePath));
            } catch (IOException e) {
                LOG.error(e.toString(), e);
            }
        }
        System.out.println("copy complete!!!");
    }

    private void fillFromFiles(File fromFile, List<File> fromFiles) {
        final File[] files = fromFile.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (ignoreFiles.contains(pathname.getName())) {
                    return false;
                }

                if (!ignoreSuffix.isEmpty()) {
                    for (String ignoreSuffix : ignoreSuffix) {
                        if (pathname.getName().endsWith(ignoreSuffix)) {
                            return false;
                        }
                    }
                }

                if (!ignorePrefix.isEmpty()) {
                    for (String prefix : ignorePrefix) {
                        if (pathname.getName().startsWith(prefix)) {
                            return false;
                        }
                    }
                }

                if (ignoreFilter != null) {
                    return ignoreFilter.accept(pathname);
                }

                return true;
            }
        });
        for (File file : files) {
            if (file.isFile()) {
                fromFiles.add(file);
            } else if (file.isDirectory()) {
                fillFromFiles(file, fromFiles);
            }
        }
    }

}
